<template>

  <div class="container" style="white-space: nowrap; height: 100%;">
    <div class="card text-center p-3 m-0">
      <h3 class=" mb-3 mt-3" v-for="(user, index) in Localuser" :key="index">
        客户端: {{ user.client_id }}
      </h3>
    </div>
  </div>
  <div class="container" style="white-space: nowrap; height: 100%;">
    <div class="card text-center">
      <div class="card-body">
        <h5 class="card-title">用户信息</h5>
        <div class="table-responsive">
          <table class="table">
            <thead>
              <tr>
<!--                <th scope="col">用户</th>-->
                <th scope="col">客户端设置</th>
                <th scope="col">数据集设置</th>
                <th scope="col">模型状态</th>
                <th scope="col">验证结果</th>
                <th scope="col">追踪</th>
                <th scope="col">追踪结果</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(user, index) in Localuser" :key="index">
<!--                <td>{{ user.name }}</td>-->
                <td>
                  <select v-model="user.setting" class="form-select">
                    <option v-for="(option, optionIndex) in settingOptions" :key="optionIndex">{{ option }}</option>
                  </select>
                </td>
                <td>
                  <select v-model="user.dataset" class="form-select">
                    <option v-for="(option, optionIndex) in settingData" :key="optionIndex">{{ option }}</option>
                  </select>
                </td>
                <td>{{ user.status }}</td>
                <td>{{ user.result1 }}</td>
                <td>
                  <button class="btn bg-primary-heavy text-white" @click="startProcess(user, index)">请求追踪</button>
                </td>
                <td v-html="formatResult(user.result2)"></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>

  <!-- 按钮 -->
  <div class="container mt-0" style="white-space: nowrap; height: 100%;">
    <div class="card mt-4 text-center">
      <div class="card-body">
        <div class="row mt-2 mb-2">
          <div class="col">
            <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%" @click="handleButtonClick(1)">
              初始化
            </button>
          </div>
          <div class="col">
            <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%" @click="handleButtonClick(2)">开始训练</button>
          </div>
          <div class="col">
            <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%" @click="handleButtonClick(3)">
              上传模型
            </button>
          </div>
<!--          <div class="col">-->
<!--            <button class="btn btn-primary btn-lg" style="width: 100%; height: 100%" @click="handleButtonClick(4)">-->
<!--              接收模型-->
<!--            </button>-->
<!--          </div>-->
          <div class="col">
            <button class="btn bg-primary-heavy text-white btn-lg " style="width: 100%; height: 100%" @click="handleButtonClick(5)">
              验证模型
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>

    <div class="container mt-4"  style="white-space: nowrap; height: 100%;">
    <div class="card mt-0 text-center">
       <div class="card-body  ">

         <div class="row mt-0 mb-2 me-4">
            <button class="btn bg-primary-heavy text-white "  @click="downloadFile">导出模型文件</button>
         </div>
         <div class="row mt-0 mb-2 me-4">
            <button class="btn bg-primary-heavy text-white "  @click="downloadFile1">下载demo.py和model.pth的使用说明</button>
         </div>
       </div>

    </div>
    <div class=" mt-2 ms-6 ">
      <p>注：导出的模型文件model.pth可以通过相应的模型代码直接加载并使用</p>
      <p>   具体使用方法可以查看model.pth使用说明</p>
<!--      <pre style="font-size: 18px;">例如：model_path = './model.pth'</pre>-->
<!--      <pre style="font-size: 18px;">     if os.path.isfile(model_path):</pre>-->
<!--      <pre style="font-size: 18px;">        model.load_state_dict(torch.load(model_path))</pre>-->
<!--      <pre style="font-size: 18px;">        print("模型加载成功。")</pre>-->

    </div>
  </div>
</template>

<script setup>
import {onMounted, onUnmounted, ref} from 'vue';
import {useStore} from "vuex";
import axios from 'axios';
import {io} from 'socket.io-client';

const initialUser = [
  {
    name: 'user1',
    setting: '默认设置',
    dataset: '数据集一',
    status: '未训练',
    result1: '未验证',
    result2: 'a55f66d4-a2fd-453e-96d0-984f7e5ef788,3974a7cf-4af8-427a-b51d-2dc320eab6f4,12ac1de4-f117-4c8b-87d6-cc5a5623d754\n',
    client_id: '1'
  },
];
const initialDataset = ['数据集一', '数据集二', '数据集三']
const Localuser = ref([]);
const settingOptions = ['默认设置', '伪造hash', '伪造签名1', '伪造签名2'];
const settingData = ref([]); // 使用 ref 来保证 reactivity

const loadUsersFromSessionStorage = () => {
  try {
    const storedDataset = JSON.parse(sessionStorage.getItem('local_dataset'));
    if (storedDataset && Array.isArray(storedDataset)) {
      settingData.value = storedDataset;
    } else {
      settingData.value = [...initialDataset];
    }
  } catch (error) {
    console.error('Error loading users from sessionStorage:', error);
    settingData.value = [...initialDataset];
  }
  try {
    const storedUser = JSON.parse(sessionStorage.getItem('local_user'));
    if (storedUser && Array.isArray(storedUser)) {
      Localuser.value = storedUser;
    } else {
      Localuser.value = [...initialUser];
    }
  } catch (error) {
    console.error('Error loading users from sessionStorage:', error);
    Localuser.value = [...initialUser];
  }

};

const saveUsersToSessionStorage = () => {
  try {
    sessionStorage.setItem('local_user', JSON.stringify(Localuser.value));
    sessionStorage.setItem('local_dataset', JSON.stringify(settingData.value));
  } catch (error) {
    console.error('Error saving users to sessionStorage:', error);
  }
};

// 设置axios
const apiBaseUrl = (window.webConfig && window.webConfig.Client1BaseUrl);
const apiClient = axios.create({
  baseURL: apiBaseUrl, // 基础URL
  timeout: 5000,
});

// WebSocket setup
let socket;
const connectWebSocket = () => {
  socket = io(apiBaseUrl); // 请确保这个 URL 与后端 WebSocket 服务器一致

  socket.on('connect', () => {
    console.log('WebSocket connected');
  });

  // socket.on('update_datasets', (data) => {
  //   console.log('Received update_datasets:', data);  // 打印接收到的数据
  //   if (data && data.datasets) {
  //     settingData.value = data.datasets;
  //   } else {
  //     console.error('update_datasets event data is malformed:', data);
  //   }
  // });

  socket.on('update', (data) => {
    if (data && typeof data.status === 'boolean') {
      Localuser.value.forEach(user => {
        user.status = '已接收';
      });
      saveUsersToSessionStorage();

    } else {
      console.warn('收到的消息格式不正确:', data);
    }
    alert("聚合结果已接收");
  });

  socket.on('return_result', (data) => {

    Localuser.value.forEach(user => {
      user.result2 = data.unhonest_participant.join(",");
    });
    saveUsersToSessionStorage();
    alert("追踪结果已返回");

  });

  socket.on('agg_verify', () => {
    alert("聚合服务器验证未通过，请重新训练模型");
  });

  socket.on('disconnect', () => {
    console.log('WebSocket disconnected, reconnecting...');
    setTimeout(connectWebSocket, 1000);
  });
};

// 设置值转换函数
const convertSettingToNumber = (setting) => {
  switch (setting) {
    case '默认设置':
      return 0;
    case '伪造hash':
      return 1;
    case '伪造签名1':
      return 2;
    case '伪造签名2':
      return 3;
    default:
      return -1; // 或其他合适的默认值
  }
};

//限制按钮在未响应前点击
const isProcessing = ref(false);
const startProcess = async (user) => {
  if (isProcessing.value) {
    alert('请求正在处理中...');
    return;
  }
  isProcessing.value = true;
  user.result2 = '处理中...';
  alert("客户端请求追踪恶意参与方...");
  try {
    // const response = await axios.post(`${process.env.VUE_APP_BACKEND_API}/Client.vue`, {
    const response = await apiClient.post(`/request_trace`);

    if (response.status === 200) {

      console.log('已请求追踪', response.data);
    }
  } catch (error) {
    console.error('请求失败:', error);
  } finally {
    isProcessing.value = false;
  }
};

// 限制按钮在未响应前点击
let isButtonClicked = false;
const handleButtonClick = async (buttonId) => {
  try {
    // 检查按钮是否已经被点击，如果是，则直接返回
    if (isButtonClicked) {
      alert('正在等待上一次请求的响应，请稍后...');
      console.log('按钮已经被点击，正在等待上一次请求的响应...');
      return;
    }
    // 按钮被点击，设置状态为 true
    isButtonClicked = true;
    let response;
    let settings = [];
    let datasets = [];

    switch (buttonId) {
      case 1:
        // 初始化前端页面
        Localuser.value.forEach(user => {
          user.setting = '默认设置';
          user.status = '未训练';
          user.result1 = '未验证';
          user.result2 = '';
        });
        alert("客户端已开始初始化操作...");
        try {
          response = await apiClient.post(`/init`);
          console.log('初始化成功', response.data);
          // 更新数据集选项
          settingData.value = response.data.datasets;
          Localuser.value.forEach(user => {
            user.dataset = response.data.datasets[0];
            user.client_id = response.data.client_id;
          });
          alert("客户端初始化完成")
        } catch (error) {
          console.error('初始化失败', error);
        }

        saveUsersToSessionStorage();
        break;
      case 2:
        alert("客户端模型已开始训练，请耐心等待...");
        try {
          // 统计所有用户的setting值，并向后端发送请求
          settings = Localuser.value.map(user => convertSettingToNumber(user.setting));
          datasets = Localuser.value.map(user => (user.dataset));
          response = await apiClient.post('/local_train', {local_setting: settings[0], local_dataset: datasets[0]});
          Localuser.value.forEach(user => {
            user.status = '训练完成';
          });
          console.log('训练完成', response.data);
          saveUsersToSessionStorage();
          alert("客户端训练完成")
        } catch (error) {
          console.error('训练失败', error);
        }
        console.log('开始训练');
        break;
      case 3:
        response = await apiClient.post('/upload', {local_settings: settings, local_datasets: datasets});
        console.log('上传模型');
        Localuser.value.forEach(user => {
          user.status = '已上传';
        });
        saveUsersToSessionStorage();
        break;
      case 4:
        console.log('接收模型');
        // 逻辑代码
        break;
      case 5:
        alert("客户端开始验证聚合模型...");
        try {
          response = await apiClient.post('/verify');
          console.log('验证完成', response.data);
          if (response.data.verify_result) {
            Localuser.value.forEach(user => {
              user.result1 = '验证成功';
            });
          } else {
            Localuser.value.forEach(user => {
              user.result1 = '验证失败';
            });
          }
          alert("客户端验证完成");
        } catch (error) {
          console.error('验证', error);
        }
        console.log('验证模型');
        // 逻辑代码
        saveUsersToSessionStorage();
        break;
      default:
        break;
    }
  } catch (error) {
    console.error('Error handling button click:', error);
  } finally {
    // 在请求完成后，重置按钮点击状态
    isButtonClicked = false;
  }
};

const downloadFile = async () => {
  try {
    // const response = await axios.get(`${process.env.VUE_APP_BACKEND_API}/Getmodel`, {
    const response = await apiClient.get(`/Getmodel`, {
      responseType: 'blob', // Important to receive the file as a Blob

    });

    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'model.pth'); // or any other extension
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  } catch (error) {
    console.error('Error downloading file:', error);
  }
};
const downloadFile1 = async () => {
  try {
    // const response1 = await axios.get(`${process.env.VUE_APP_BACKEND_API}/Getfiles`, {
    const response1 = await apiClient.get(`/Getfiles`, {
      responseType: 'blob',
      params: {
        file: "guide"
      }
    });

    const response2 = await apiClient.get(`/Getfiles`, {
      responseType: 'blob',
      params: {
        file: "demo"
      }
    });

    const url1 = window.URL.createObjectURL(new Blob([response1.data]));
    const url2 = window.URL.createObjectURL(new Blob([response2.data]));

    const link1 = document.createElement('a');
    link1.href = url1;
    link1.setAttribute('download', 'model.pth的使用说明.docx'); // 设置第一个文件的下载属性
    document.body.appendChild(link1);
    link1.click();
    document.body.removeChild(link1);

    const link2 = document.createElement('a');
    link2.href = url2;
    link2.setAttribute('download', 'demo.py'); // 设置第二个文件的下载属性
    document.body.appendChild(link2);
    link2.click();
    document.body.removeChild(link2);
  } catch (error) {
    console.error('Error downloading files:', error);
  }
};

const formatResult = (result) => {
  return result.split(',').map(item => item.trim()).join('<br>');
};

const store = useStore();
const hideSidebar = () => store.commit('hideSidebar');
const showSidebar = () => store.commit('showSidebar');

onMounted(() => {
  hideSidebar();
  loadUsersFromSessionStorage();
  connectWebSocket();
});

onUnmounted(() => {
  showSidebar();
  saveUsersToSessionStorage();
  if (socket) {
    socket.disconnect();
  }
});
</script>


<style scoped>
.container {
  margin-top: 20px;
}

.card {
  margin-top: 10px;
}

.table-responsive {
  max-height: 400px;
  overflow-y: auto;
}

table {
  width: 100%;
  margin-bottom: 1rem;
  color: #212529;
  border-collapse: separate;
  border-spacing: 1px 2px;
}

.btn-secondary {
  background-color: #6c757d;
}

.btn-secondary.disabled {
  background-color: #e9ecef;
  cursor: not-allowed;
}

.bg-primary-light {
  background-color: #5e72e4 !important; /* 淡蓝色 */
}

.bg-secondary-light {
  background-color: #aba8a8 !important; /* 淡灰色 */
}

.btn-secondary.disabled {
  pointer-events: none;
  opacity: 1;
}

.disabled1 {
  pointer-events: none;
  opacity: 1;
}

.bg-primary-heavy {
  background-color: #152ca8 !important; /* 淡蓝色 */
}

.bg-danger-light {
  background-color: #a12004 !important; /* 淡灰色 */
}

.btn-secondary.disabled {
  pointer-events: none;
  opacity: 1;
}

.disabled1 {
  pointer-events: none;
  opacity: 1;
}

</style>
